#pragma once

#include <atlctrls.h>
#include <atlmisc.h>
#include <atlscrl.h>
#include <atlframe.h>
#include <atlwince.h>

#include <atlcrack.h>

template <class T, UINT t_shidiFlags, bool t_bModal = true> class CCEStandartDialog
    : public ATL::CDialogImpl< T >
{
public:
    void StdShidInit()
    {
        T* pT = static_cast<T*>(this);
        SHINITDLGINFO shidi = { SHIDIM_FLAGS, pT->m_hWnd, t_shidiFlags };
        ::SHInitDialog(&shidi);
    }

    bool OnClose()
    {
        return true;
    }

    LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
    {
        T* pT = static_cast<T*>(this);

        if (!pT->OnClose())
            return 0;

        if (t_bModal)
            ::EndDialog(pT->m_hWnd, wID);
        else
            pT->DestroyWindow();
        return 0;
    }

    BEGIN_MSG_MAP(CCEStandartDialog)
        MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
        COMMAND_RANGE_HANDLER(IDOK, IDCANCEL, OnCloseCmd)
    END_MSG_MAP()

    LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
    {
#ifdef _DEBUG // _DEBUG must be defined before atlwin.h inclusion
        T* pT = static_cast<T*>(this);
        ATLASSERT(t_bModal == pT->m_bModal);
#endif
        StdShidInit();
        return bHandled = FALSE;
    }
};

template <class T, UINT t_shidiFlags, bool t_bModal = true> class CCEResizableDialog 
    : public CCEStandartDialog< T, t_shidiFlags, t_bModal >
{
public:

    CCEResizableDialog<T, t_shidiFlags, t_bModal> ()
    {
        SHACTIVATEINFO sai = { sizeof(SHACTIVATEINFO) };
        m_sai = sai;
    }

   BEGIN_MSG_MAP_EX(CCEResizableDialog)
        MESSAGE_HANDLER(WM_ACTIVATE, OnActivate)
        MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingsChange)
        MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
        COMMAND_RANGE_HANDLER(IDOK, IDCANCEL, OnCloseCmd)
    END_MSG_MAP()

    LRESULT OnActivate(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        T* pT = static_cast<T*>(this);
        ::SHHandleWMActivate(pT->m_hWnd, wParam, lParam, &m_sai, 0);
        return bHandled = FALSE;
    }

    LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
    {
#ifdef _DEBUG // _DEBUG must be defined before atlwin.h inclusion
        T* pT = static_cast<T*>(this);
        ATLASSERT(t_bModal == pT->m_bModal);
#endif
        StdShidInit();

        SIPINFO si;
        memset( &si, 0, sizeof( si ) );
        si.cbSize = sizeof( si );

        if( SHSipInfo( SPI_GETSIPINFO, 0, &si, 0 ) && ( si.fdwFlags & SIPF_ON ) ) 
        {
            MoveWindow( si.rcVisibleDesktop.left
                      , si.rcVisibleDesktop.top
                      , si.rcVisibleDesktop.right - si.rcVisibleDesktop.left
                      , si.rcVisibleDesktop.bottom - si.rcVisibleDesktop.top
                      , TRUE );
        }

        return bHandled = FALSE;
    }

    LRESULT OnSettingsChange(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        T* pT = static_cast<T*>(this);
	    SHHandleWMSettingChange(pT->m_hWnd, wParam, lParam, &m_sai);
        return bHandled = FALSE;
    }

protected:
    SHACTIVATEINFO m_sai;
};

template <class T, UINT t_shidiFlags, bool t_bModal = true> class CCEOrientedDialog 
: public CCEResizableDialog< T, t_shidiFlags, t_bModal >
{
public:

    BOOL SetOrientation(DRA::DisplayMode mode)
    {
        T* pT = static_cast<T*>(this);
        ATLASSERT(pT->IsWindow());
        ATLASSERT(mode == DRA::GetDisplayMode());

        UINT iResource = (mode == DRA::Landscape) ? T::IDD_LANDSCAPE : T::IDD;
        BOOL bRes = DRA::RelayoutDialog(ATL::_AtlBaseModule.GetResourceInstance(), pT->m_hWnd, MAKEINTRESOURCE(iResource));

        pT->OnOrientation(mode);
        return bRes;
    }

    // Override
    void OnOrientation(DRA::DisplayMode /*mode*/)
    {}

    BEGIN_MSG_MAP_EX(CCEResizableDialog)
        MESSAGE_HANDLER(WM_ACTIVATE, OnActivate)
        MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingsChange)
        MESSAGE_HANDLER(WM_SIZE, OnSize)
        MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
        COMMAND_RANGE_HANDLER(IDOK, IDCANCEL, OnCloseCmd)
    END_MSG_MAP()

    LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
#ifdef _DEBUG // _DEBUG must be defined before atlwin.h inclusion
        T* pT = static_cast<T*>(this);
        ATLASSERT(t_bModal == pT->m_bModal);
#endif
        if (DRA::GetDisplayMode() == DRA::Landscape)
            SetOrientation(DRA::Landscape);

        return CCEResizableDialog< T, t_shidiFlags, t_bModal >::OnInitDialog(uMsg, wParam, lParam, bHandled);
    }

    LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
    {
        SetOrientation(DRA::GetDisplayMode());
        return bHandled = FALSE;
    }
};